
#include <list>
#include "structure/Predicate.h"
#include "structure/Rule.h"
#include "structure/SubGoal.h"
#include "RDFSUtil.h"
#include <map>

#ifndef _RDFPROCESSOR_H_
#define _RDFPROCESSOR_H_
class RDFSProcessor{
private:
	int recursion;

public:
	RDFSProcessor(){
		recursion=0;
	}
	std::list<Rule> loadRules(){
		std::list<Rule> list;
		Term X("?x");
		Term Y("?y");
		Term Z("?z");
		Term P("?p");
		Term P1("?p1");
		Term SC(RDFSSUBCLASS);
		Term SP(RDFSSUBPROPERTY);
		Term RT(RDFTYPE);
		Term RD(RDFSDOMAIN);
		Term RR(RDFSRANGE);

		//1st rule
		Predicate subClass("subClass",X,Y);
		Rule r1(1);
		std::list<Predicate> l;
		Predicate rdfsTriples("triple",X,SC,Y);
		l.push_back(rdfsTriples);
		r1.createRule(subClass,l);
		list.push_back(r1);

		//2st rule
		Predicate subClass2("subClass",X,Y);
		Rule r2(2);
		std::list<Predicate> l2;
		Predicate rdfsTriples2("triple",X,SC,Z);
		l2.push_back(rdfsTriples2);
		Predicate subClass22("triple",Z,SC,Y);
		l2.push_back(subClass22);
		r2.createRule(subClass2,l2);
		list.push_back(r2);

		//3rd rule
		Predicate subProperty("subProperty",X,Y);
		std::list<Predicate> l3;
		Predicate rdfsTriples3("triple",X,SP,Y);
		l3.push_back(rdfsTriples3);
		Rule r3(3);
		r3.createRule(subProperty,l3);
		list.push_back(r3);

		//4th rule(rdfs5)
		Predicate subProperty2("subProperty",X,Y);
		std::list<Predicate> l4;
		Predicate rdfsTriples4("triple",X,SP,Z);
		l4.push_back(rdfsTriples4);
		Predicate subProperty22("triple",Z,SP,Y);
		l4.push_back(subProperty22);
		Rule r4(4);
		r4.createRule(subProperty2,l4);
		list.push_back(r4);

		//8th rule
		Predicate type1("type",X,Y);
		std::list<Predicate> l8;
		Predicate rdfTriple("triple",X,RT,Y);
		l8.push_back(rdfTriple);
		Rule r8(8);
		r8.createRule(type1,l8);
		list.push_back(r8);

		//9th rule(rdfs9)
		Predicate type2("type",X,Y);
		std::list<Predicate> l9;
		Predicate rdfTriple2("triple",X,RT,Z);
		l9.push_back(rdfTriple2);
		Predicate rdfTriple22("triple",Z,SC,Y);
		l9.push_back(rdfTriple22);
		Rule r9(9);
		r9.createRule(type2,l9);
		list.push_back(r9);

		//10th rule(rdfs2)
		Predicate type3("type",X,Y);
		std::list<Predicate> l10;
		Predicate rdfTriple3("triple",X,P,Z);
		l10.push_back(rdfTriple3);
		Predicate rdfsTriple3("triple",P,RD,Y);
		l10.push_back(rdfsTriple3);
		Rule r10(10);
		r10.createRule(type3,l10);
		list.push_back(r10);

		//11th rule(rdfs3)
		Predicate type4("type",X,Y);
		std::list<Predicate> l11;
		Predicate rdfTriple4("triple",Z,P,X);
		l11.push_back(rdfTriple4);
		Predicate rdfsTriple4("triple",P,RR,Y);
		l11.push_back(rdfsTriple4);
		Rule r11(11);
		r11.createRule(type4,l11);
		list.push_back(r11);


		//13th rule
		Predicate genTriple5("genTriple",X,P,Y);
		std::list<Predicate> l13;
		Predicate rdfTriple6("triple",X,P,Y);
		l13.push_back(rdfTriple6);
		Rule r13(13);
		r13.createRule(genTriple5,l13);
		list.push_back(r13);

		//12th rule
		Predicate genTriple4("genTriple",X,P,Y);
		std::list<Predicate> l12;
		Predicate rdfTriple5("triple",X,P1,Y);
		l12.push_back(rdfTriple5);
		Predicate subproperty("triple",P1,SP,P);
		l12.push_back(subproperty);
		Rule r12(12);
		r12.createRule(genTriple4,l12);
		list.push_back(r12);

		return list;

	}
	std::list<std::list<Predicate> > processRDFS(Predicate p) {
		std::list<Rule> list = loadRules();
		recursion++;
		std::cout << "recursion =" << recursion << std::endl;
		std::list<std::list<Predicate> > goals;
		std::cout << "RDFS processor: pred=" << p.toString() << std::endl;

		std::list<Rule>::iterator begin = list.begin();
		std::list<Rule>::iterator end = list.end();
		for (std::list<Rule>::iterator r = begin; r != end; r++) {
			std::list<Predicate> g;
			std::cout << "rule" << r->ruleNum << "= " << r->toString()
					<< std::endl;
			int rule = r->match(p);
			std::cout << "satisfied= " << rule << std::endl;
			if (rule != -1) {
				Rule r1;
				std::list<std::string> pvars = p.getVariablesNames();
				std::list<std::string> rvars = r->getVariablesNames();
				if (varCollision(pvars, rvars)) {
					std::cout << "COLLISION!" << std::endl;
					r1 = r->renameVariable(r->ruleNum, recursion);
				} else
					r1 = *r;
				std::cout << "hear= " << r1.getHead(rule).toString()
						<< std::endl;
				std::cout << "body= ";
				std::list<Predicate> body_list = r1.getBody(rule);
				std::list<Predicate>::iterator body_beg = body_list.begin();
				std::list<Predicate>::iterator body_end = body_list.end();
				std::map<std::string,Term> sub = r1.getSubstitution(p);
				std::cout << "substitution= ";
				std::map<std::string,Term>::iterator map_it=sub.begin();
				while(map_it!=sub.end()){
//					std::cout<< map_it->first << "------>" << map_it->second.getName()<< std::endl;
					++map_it;
				}

				std::list<std::list<Predicate> > newlist;
				for (std::list<Predicate>::iterator i = body_beg; i != body_end; i++) {

					Predicate p1=i->applySubstitution(sub);
//					std::cout << "-----------after application: " << p1.toString() << "-----------------" << std::endl;

					if (!p1.getName().compare("triple")) {    //p1.getName()=="triple"
						g.push_back(p1);
						std::cout << p1.toString() << std::endl;
					} else {
						std::cout << "recursion call!!!!" << std::endl;
						newlist = processRDFS(p1);
						std::cout << "==================newlist 1:"
								<< std::endl;
					}
				}

				std::list<std::list<Predicate> >::iterator it_beg =
						newlist.begin();
				std::list<std::list<Predicate> >::iterator it_end =
						newlist.end();
				for (std::list<std::list<Predicate> >::iterator it = it_beg; it
						!= it_end; it++) {
					std::list<Predicate> g1;
					std::list<Predicate>::iterator g_beg = g.begin();
					std::list<Predicate>::iterator g_end = g.end();
					for (std::list<Predicate>::iterator it5 = g_beg; it5
							!= g_end; it5++)
						g1.push_back(*it5); //g1.addAll(g) in Java
					std::list<Predicate> it2 = *it;
					std::list<Predicate>::iterator it2_beg = it2.begin();
					std::list<Predicate>::iterator it2_end = it2.end();
					for (std::list<Predicate>::iterator it6 = it2_beg; it6
							!= it2_end; it6++) {
						g1.push_back(*it6);
					}
					goals.push_back(g1);
				}
				if (newlist.empty())
					goals.push_back(g);
			}

		}

		return goals;
	}
	~RDFSProcessor(){}

	std::list<SubGoal> getSubgoals(std::list<std::list<Predicate> > g, std::string key){
		std::cout << "Key= " << key << std::endl;
		std::list<SubGoal> gs;
		std::list<std::list<Predicate> >::iterator g_beg = g.begin();
		std::list<std::list<Predicate> >::iterator g_end = g.end();
		for(std::list<std::list<Predicate> >::iterator i=g_beg;i!=g_end;i++){
			std::list<Predicate> plist=*i;
			std::list<Predicate> tmp;
			tmp=plist;
			SubGoal sg;
			int counter=0;  //确保尾巴里面含有两个同样的key，只能选取一个作为头，另外一个作为尾巴。
			std::list<Predicate>::iterator plist_beg=plist.begin();
			std::list<Predicate>::iterator plist_end=plist.end();
			for(std::list<Predicate>::iterator it=plist_beg;it!=plist_end && counter<1;it++){
				Predicate p(*it);
				if(p.contains(key)){
					counter++;
					std::cout << "counter++" << std::endl;
					sg.setHead(p);
					tmp.remove(p);
				}
			}
			if(counter==0){		//如果找过了一轮，还是没有找到key，那么则意味着这种key需要变化
				for(std::list<Predicate>::iterator it=plist_beg;it!=plist_end && counter<1;it++){
					Predicate p(*it);
					std::string key2;
					if(p.argument1.getType()==RDFS_ATOM){
						key2=p.argument1.getName();
					}else if(p.argument3.getType()==RDFS_ATOM){
						key2=p.argument3.getName();
					}else if(p.argument2.getType()==RDFS_ATOM){
						key2=p.argument2.getName();
					}
					if(p.contains(key2)){
						counter++;
						std::cout << "counter++" << std::endl;
						sg.setHead(p);
						tmp.remove(p);
					}
				}
			}
			sg.setTail(tmp);
			gs.push_back(sg);
		}
		return gs;
	}

};

#endif
